#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <nlohmann/json.hpp>
#include "../include/httplib.h"
#include "../include/client.h"


using json = nlohmann::json;

std::vector<std::string> sort_points_urls = {
    "http://127.0.0.1:8000"
};
// 定义可用的 URL 列表
// std::vector<std::string> sort_points_urls = {
//     "http://hustcsib.icu:40204", 
//     "http://hustcsib.icu:40205"
// };
// 计算两点之间的欧氏距离
double calculate_distance(const Point& p1, const Point& p2) {
    return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
}

// 发送 HTTP POST 请求并获取响应
json send_request(const std::string& url, const json& data) {
    httplib::Client cli(url.c_str());
    auto res = cli.Post("/sort_points", data.dump(), "application/json");
    if (res && res->status == 200) {
        return json::parse(res->body);
    } else {
        throw std::runtime_error("请求失败或响应无效");
    }
}

// 获取下一个 URL（循环使用）
std::string get_next_url(const std::vector<std::string>& urls, int& index) {
    std::string url = urls[index % urls.size()];
    index++;
    return url;
}

// 处理任务点并获取结果
std::vector<Point> get_sorted_result(const std::vector<Point>& task_points, const Point& start_point,int& url_index){
    // 计算到目标点的距离
    Point target_point = start_point;
    // 起点尽量靠近中心，所以找出距离中心点最近的为起点
    std::vector<double> distances;
    for (const auto& point : task_points) {
        distances.push_back(calculate_distance(point, target_point));
    }

    // 找到最近的点作为起点
    auto min_it = std::min_element(distances.begin(), distances.end());
    Point real_start_point = task_points[std::distance(distances.begin(), min_it)];

    // 准备发送的数据
    json send_data;
    // 将 points 转换为二维数组格式
    for (const auto& point : task_points) {
        send_data["points"].push_back({point.x, point.y});
    }
    // 将 start_point 转换为数组格式
    send_data["start_point"] = {real_start_point.x, real_start_point.y};

    // 发送请求并获取结果
    std::string url = get_next_url(sort_points_urls, url_index);
    json response = send_request(url, send_data);

    // 解析响应并返回排序后的点
    std::vector<Point> sorted_points;
    for (const auto& index : response["sorted_indices"]) {
        sorted_points.push_back(task_points[index.get<size_t>()]);
    }

    return sorted_points;
}
